﻿using System.Collections.Generic;
using Core;
using Core.CSV;
using Core.File;
using Game.View;
using Newtonsoft.Json;
using UnityEngine;

namespace Game {
    /// <summary>
    /// 武器基类
    /// </summary>
    public partial class Weapon : ABSWeaponCombinant, ISerializable<Weapon> {
        public WeaponDisplay GameInstance { get; private set; }
        public TBWeaponsConfig Data { get; private set; }
        private List<WeaponEffect> mEffects;
        private List<WeaponEffect> mSkillEffects;

        public string Name {
            get;
            private set;
        }
        public bool IsLock { get; private set; }

        //是否可释放攻击
        public bool isActive { get; private set; }

        //是否可释放技能
        public bool isSkillActive { get; private set; }
        
        private int mCurEndComponentsNum = 0;

        public Weapon() { }
        
        public Weapon(TBWeaponsConfig config) {
            Data = config;
            Name = Data.Name;
            //效果列表初始化
            mEffects = ListUtils.CreateList<WeaponEffect>(config.EffectCapacity);
            mSkillEffects = ListUtils.CreateList<WeaponEffect>(config.SkillEffectCapacity);
        }

        public void AttachInstance(WeaponDisplay obj) {
            GameInstance = obj;
        }

        public void Init() {
            onInit();
        }

        protected virtual void onInit() {
        }
        
        /// <summary>
        /// 武器触发
        /// </summary>
        public void Trigger() {
            if (IsLock) {
                return;
            }

            IsLock = true;
            onTrigger();
        }

        protected virtual void onTrigger() {
            //触发效果
            for (int i = 0; i < mEffects.Count; ++i) {
                mEffects[i]?.Trigger();
            }

            //触发组件
            foreach (var component in mWeaponComponentsDic) {
                component.Value.Trigger();
            }
            
            
            //结束触发
            MonoHelper.Ins.StartCoroutine(mTriggerEndFlag,onTriggerEnd);
        }

        protected virtual void onTriggerEnd() {
            for (int i = mEffects.Count - 1; i >= 0; --i) {
                mEffects[i]?.TriggerEnd();
            }
            Reset();
        }
        
        /// <summary>
        /// 武器技能
        /// </summary>
        public void SkillTrigger() {
            if (IsLock) {
                return;
            }
            onSkillTrigger();
        }
        
        protected virtual void onSkillTrigger(){}

        public void Reset() {
            IsLock = false;
            mTriggerEndFlag.Value = false;
            mCurEndComponentsNum = 0;
        }


        public string Serialize() {
            List<string> list = new List<string>();
            string data = JsonConvert.SerializeObject(Data);
            list.Add(data);
            list.Add(Name);
            for (int i = 0; i < mEffects.Count; ++i) {
                if (mEffects[i] == null) {
                    continue;
                }
                list.Add(string.Format("{0}_{1}",mEffects[i].Data.ID,i));
            }

            string saveData = StringUtils.Combine(list.ToArray()); 
            return saveData;
        }

        public void Deserialize(string data) {
            string[] readData = StringUtils.Split(data);
            Data = JsonUtility.FromJson<TBWeaponsConfig>(readData[0]);
            mEffects = ListUtils.CreateList<WeaponEffect>(Data.EffectCapacity);
            mSkillEffects = ListUtils.CreateList<WeaponEffect>(Data.SkillEffectCapacity);
            Name = readData[1];
            for (int i = 2; i < readData.Length; ++i) {
                string[] effect = readData[i].Split("_");
                mEffects[int.Parse(effect[1])] = WeaponEffectFactory.New(uint.Parse(effect[0]));
            }
        }


        public static Weapon DeseralizeWeapon(string data) {
            string[] readData = StringUtils.Split(data);
            TBWeaponsConfig config = JsonUtility.FromJson<TBWeaponsConfig>(readData[0]);
            Weapon weapon = WeaponFactory.New(config);
            weapon.Deserialize(data);
            return weapon;
        }
    }
}